From 2bb899b5c02d09b860e3cebc70511b1a0cfd03a2 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 21 Dec 2011 17:40:16 +0100 Subject: [PATCH] cssimage: Add a few convenience functions --- gtk/gtkcssimage.c | 153 +++++++++++++++++++++++++++++++++++++++ gtk/gtkcssimageprivate.h | 12 +++ 2 files changed, 165 insertions(+) diff --git a/gtk/gtkcssimage.c b/gtk/gtkcssimage.c index d907e64214..232c2ae65c 100644 --- a/gtk/gtkcssimage.c +++ b/gtk/gtkcssimage.c @@ -160,6 +160,159 @@ _gtk_css_image_print (GtkCssImage *image, klass->print (image, string); } +/* Applies the algorithm outlined in + * http://dev.w3.org/csswg/css3-images/#default-sizing + */ +void +_gtk_css_image_get_concrete_size (GtkCssImage *image, + double specified_width, + double specified_height, + double default_width, + double default_height, + double *concrete_width, + double *concrete_height) +{ + double image_width, image_height, image_aspect; + + g_return_if_fail (GTK_IS_CSS_IMAGE (image)); + g_return_if_fail (specified_width >= 0); + g_return_if_fail (specified_height >= 0); + g_return_if_fail (default_width > 0); + g_return_if_fail (default_height > 0); + g_return_if_fail (concrete_width != NULL); + g_return_if_fail (concrete_height != NULL); + + /* If the specified size is a definite width and height, + * the concrete object size is given that width and height. + */ + if (specified_width && specified_height) + { + *concrete_width = specified_width; + *concrete_height = specified_height; + return; + } + + image_width = _gtk_css_image_get_width (image); + image_height = _gtk_css_image_get_height (image); + image_aspect = _gtk_css_image_get_aspect_ratio (image); + + /* If the specified size has neither a definite width nor height, + * and has no additional contraints, the dimensions of the concrete + * object size are calculated as follows: + */ + if (specified_width == 0.0 && specified_height == 0.0) + { + /* If the object has only an intrinsic aspect ratio, + * the concrete object size must have that aspect ratio, + * and additionally be as large as possible without either + * its height or width exceeding the height or width of the + * default object size. + */ + if (image_aspect > 0 && image_width == 0 && image_height == 0) + { + if (image_aspect * default_height > default_width) + { + *concrete_width = default_height * image_aspect; + *concrete_height = default_height; + } + else + { + *concrete_width = default_width; + *concrete_height = default_width / image_aspect; + } + } + + /* Otherwise, the width and height of the concrete object + * size is the same as the object's intrinsic width and + * intrinsic height, if they exist. + * If the concrete object size is still missing a width or + * height, and the object has an intrinsic aspect ratio, + * the missing dimension is calculated from the present + * dimension and the intrinsic aspect ratio. + * Otherwise, the missing dimension is taken from the default + * object size. + */ + if (image_width) + *concrete_width = image_width; + else if (image_aspect) + *concrete_width = image_height * image_aspect; + else + *concrete_width = default_width; + + if (image_height) + *concrete_height = image_height; + else if (image_aspect) + *concrete_height = image_width / image_aspect; + else + *concrete_height = default_height; + + return; + } + + /* If the specified size has only a width or height, but not both, + * then the concrete object size is given that specified width or height. + * The other dimension is calculated as follows: + * If the object has an intrinsic aspect ratio, the missing dimension of + * the concrete object size is calculated using the intrinsic aspect-ratio + * and the present dimension. + * Otherwise, if the missing dimension is present in the object's intrinsic + * dimensions, the missing dimension is taken from the object's intrinsic + * dimensions. + * Otherwise, the missing dimension of the concrete object size is taken + * from the default object size. + */ + if (specified_width) + { + *concrete_width = specified_width; + if (image_aspect) + *concrete_height = specified_width / image_aspect; + else if (image_height) + *concrete_height = image_height; + else + *concrete_height = default_height; + } + else + { + *concrete_height = specified_height; + if (image_aspect) + *concrete_width = specified_height * image_aspect; + else if (image_width) + *concrete_width = image_width; + else + *concrete_width = default_width; + } +} + +cairo_surface_t * +_gtk_css_image_get_surface (GtkCssImage *image, + cairo_surface_t *target, + int surface_width, + int surface_height) +{ + cairo_surface_t *result; + cairo_t *cr; + + g_return_val_if_fail (GTK_IS_CSS_IMAGE (image), NULL); + g_return_val_if_fail (surface_width > 0, NULL); + g_return_val_if_fail (surface_height > 0, NULL); + + if (target) + result = cairo_surface_create_similar (target, + CAIRO_CONTENT_COLOR_ALPHA, + surface_width, + surface_height); + else + result = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + surface_width, + surface_height); + + cr = cairo_create (result); + _gtk_css_image_draw (image, cr, surface_width, surface_height); + cairo_destroy (cr); + + return result; +} + GtkCssImage * _gtk_css_image_new_parse (GtkCssParser *parser, GFile *base) diff --git a/gtk/gtkcssimageprivate.h b/gtk/gtkcssimageprivate.h index 20a09a4073..1b0fc98d7a 100644 --- a/gtk/gtkcssimageprivate.h +++ b/gtk/gtkcssimageprivate.h @@ -92,6 +92,18 @@ void _gtk_css_image_draw (GtkCssImage *image, void _gtk_css_image_print (GtkCssImage *image, GString *string); +void _gtk_css_image_get_concrete_size (GtkCssImage *image, + double specified_width, + double specified_height, + double default_width, + double default_height, + double *concrete_width, + double *concrete_height); +cairo_surface_t * + _gtk_css_image_get_surface (GtkCssImage *image, + cairo_surface_t *target, + int surface_width, + int surface_height); G_END_DECLS -- 2.30.2